Persist search sheet state across close/reopen#5534
Draft
FadhlanR wants to merge 5 commits into
Draft
Conversation
FadhlanR
force-pushed
the
cs-12109-host-persist-search-sheet-state-query-filters-view-results
branch
from
July 17, 2026 07:31
6474fb0 to
48ab0d6
Compare
Contributor
Add an in-memory, session-scoped SearchSheetState service that holds the operator-mode search sheet's query, selected types/realms, sort, view, and pagination, plus a snapshot of the last results. The sheet's @mode-gated subtree is still destroyed on close (no background work while closed); on reopen it rehydrates from the service, redisplays the cached results snapshot immediately, and re-runs the query to refresh. Persistence is opt-in via a `@persist` flag passed only by the search sheet, so the card choosers keep their own ephemeral state. The service registers with the reset service, so logout/realm reset clears it; a page reload also clears it (in-memory, no localStorage). resetState now runs only on explicit Cancel/Escape (removed from plain close/blur and result-select), and reopening a persisted search opens straight to the results view. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The search sheet's result snapshot and the search resource each wrote tracked state during the render that consumed it, tripping Glimmer's mutate-after-consume assertion and failing host tests as a global error. - Capture the main-results snapshot in a microtask instead of during the modifier's render, and key it to the current wire query so a reopen only redisplays results for the same search (never stale rows under a different term, and an idle sheet never clobbers a snapshot). Extract the snapshot-vs-live decision into a pure, unit-tested helper. - Start SearchEntriesResource's search a microtask after modify so the task's isRunning write lands outside the consuming render — the case that bites when a SearchResults mounts with a query already set (the sheet reopening restored, or a chooser rendering recents). Load tracking stays synchronous via a Deferred so prerender readiness is unaffected. - Update the reopen expectation in the interact-submode acceptance test to the persisted behavior, and add acceptance + unit coverage for persist, Cancel/Escape reset, empty-then-close, and service reset. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reopening the operator-mode search sheet with an unchanged query now seeds the freshly-mounted search resource from the retained snapshot and skips the fetch, so the prior results show immediately with no re-run and no "Searching…" flash. A one-shot guard keeps the seed from re-applying, so any query change still runs a fresh search. The results-list scroll offset is captured on scroll and restored on reopen (session-only). The seeded resource holds the rows directly, so the display-time resolveMainResults snapshot path is removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The search sheet now keeps its query and filters on a plain close (click outside); only an explicit Cancel or Escape clears. Update the two operator-mode UI tests that asserted the old reset-on-blur behavior: - realm filter: selecting a realm then clicking outside and reopening keeps the realm checked. - type filter: a search term plus a type selection survive click-outside, so reopening returns to the results view with both still applied. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
FadhlanR
force-pushed
the
cs-12109-host-persist-search-sheet-state-query-filters-view-results
branch
from
July 20, 2026 12:50
7a7cbc7 to
04c73c6
Compare
The code-mode playground autogenerates a blank instance when it sees a search that has settled with no results. Starting the search resource's task a microtask after modify() (needed so a SearchResults mounting with a query already set doesn't flip isRunning mid-render and trip Glimmer's backtracking assertion) left a window where a just-set query read as settled-with-no-results — so the playground autogenerated "Untitled" instances, breaking the playground / spec / AI-assistant suites. Keep the deferred start, but have isLoading also report loading across that gap: it's true whenever a query is set and no run has completed yet, read from the untracked #previousQuery / hasCompletedFullRun fields so nothing tracked is mutated mid-render. The seed branch marks the run complete synchronously, so a seeded reopen still presents as settled with no flash. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
FadhlanR
force-pushed
the
cs-12109-host-persist-search-sheet-state-query-filters-view-results
branch
from
July 20, 2026 13:58
4b75873 to
37a7867
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves CS-12109.
Problem
Closing the operator-mode search sheet discards the entire search — reopening starts from a blank slate. The
@modegate atsearch-sheet/index.gtsdestroys the wholeSearchPanel → PanelContent → SearchResults → SearchEntriesResourcesubtree on close, dropping the query, filters, sort, view, pagination, and results.Approach
A new in-memory, session-scoped
SearchSheetStateservice holds the sheet's state (query text, selected types/realms, sort, view toggle, pagination) plus a snapshot of the last results.@mode-gated subtree is still destroyed on close, so there is no background work while the sheet is closed (the search resource and its realm subscriptions tear down).@persistflag passed only by the search sheet, so the card choosers (which render their ownSearchPanelinstances) keep their own clean, per-invocation state.resetservice, so logout / realm reset clears it. A page reload also clears it (in-memory only, nolocalStorage).resetStatenow runs only on explicit Cancel / Escape — removed from plain close/blur and from result-select, so those keep the search. Reopening a persisted search opens straight to the results view.Files
services/search-sheet-state.ts(new) — the in-memory store + results snapshot, reset-registered.search-sheet/index.gts— state backed by the service; reset only on explicit cancel.card-search/panel.gts— additiveinitialActiveSort/onSortChange/persistargs (choosers unaffected).card-search/panel-content.gts— view + pagination behind@persist; main-results snapshot capture/redisplay.operator-mode/submode-layout.gts— reopen to the results view when a search is persisted.Verification
lint:types,lint:js, andlint:hbspass inpackages/host(with boxel-icons + boxel-ui built).Remaining
🤖 Generated with Claude Code